module freq_meter #(
    parameter integer SYS_CLK_FREQ = 100000
) (
    input        sys_clk,
    input        arst_n,
    input        sig_meas_i,
    input        sig_test_i,
    input        btn_sigsel_i,
    input        btn_unitsel_i,
    output [3:0] sel_o,
    output [7:0] seg_o,
    output       led_hz_o,
    output       led_khz_o,
    output       led_overflow_o,
    output       led_mode_o
);

  wire        rstn_sync;
  wire        sig_in_s;
  wire        sig_sel_s;
  wire        unit_sel_s;
  wire        gate_ena_s;
  wire        pedge_detected_s;
  wire        pedge_timeout_s;

  wire        tbase_pulse_1ms_s;
  wire        tbase_s;

  wire [11:0] bcdcnt_s;
  wire        overflow_s;

  wire        mode_blink_s;

  rst_gen rst_gen_inst (
      .arst_n (arst_n),
      .sys_clk(sys_clk),
      .rst_n  (rstn_sync)
  );

  time_base #(
      .SYS_CLK_FREQ(SYS_CLK_FREQ)
  ) time_base_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .unit_sel_i(unit_sel_s),
      .gate_ena_i(gate_ena_s),
      .tbase_pulse_1ms_o(tbase_pulse_1ms_s),
      .tbase_o(tbase_s)
  );

  mode_switch mode_switch_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .tbase_pulse_i(tbase_pulse_1ms_s),
      .btn_sigsel_i(btn_sigsel_i),
      .btn_unitsel_i(btn_unitsel_i),
      .sig_sel_o(sig_sel_s),
      .unit_sel_o(unit_sel_s)
  );

  signal_input sig_mux_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .sig_meas_i(sig_meas_i),
      .sig_test_i(sig_test_i),
      .sig_sel_i(sig_sel_s),
      .sig_in_o(sig_in_s)
  );

  pedge_detect pedge_detect_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .sig_i(sig_in_s),
      .detect_en(tbase_s),
      .pedge_o(pedge_detected_s)
  );

  timeout_timer #(
      .NCNT(1000)
  ) timeout_dec_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .timer_en_i(tbase_s),
      .ref_pulse_i(tbase_pulse_1ms_s),
      .check_pulse_i(pedge_detected_s),
      .timeout_o(pedge_timeout_s)
  );

  pulse_cnt pulse_cnt_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .sig_in_i(sig_in_s),
      .cnt_ena_i(tbase_s),
      .bcdcnt_o(bcdcnt_s),
      .overflow_o(overflow_s)
  );

  assign gate_ena_s = pedge_timeout_s | pedge_detected_s;

  disp_ctrl disp_ctrl_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .tbase_pulse_i(tbase_pulse_1ms_s),
      .unit_sel_i(unit_sel_s),
      .bcdcnt_i(bcdcnt_s),
      .sel_o(sel_o),
      .seg_o(seg_o)
  );

  led_blink #(
      .MAX_CNT(SYS_CLK_FREQ / 2)
  ) blk_ovfl_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .blink_en(overflow_s),
      .blink_o(led_overflow_o)
  );

  // blink when test mode, sig_sel_s = 1
  led_blink #(
      .MAX_CNT(SYS_CLK_FREQ / 2)
  ) blk_mode_inst (
      .sys_clk(sys_clk),
      .rst_n(rstn_sync),
      .blink_en(sig_sel_s),
      .blink_o(mode_blink_s)
  );

  assign led_hz_o   = rstn_sync & (~unit_sel_s);
  assign led_khz_o  = rstn_sync & unit_sel_s;
  assign led_mode_o = rstn_sync & (mode_blink_s | (~sig_sel_s));

endmodule
